/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2024-07-29 13:43:51
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2024-07-29 20:10:42
 * @FilePath: /hw/110/Sig_cp/RingQueue.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <semaphore.h>
#include <pthread.h>

using namespace std;

template <typename T>
class RingQueue
{
private:
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }
    void V(sem_t &sem)
    {
        sem_post(&sem);
    }

public:
    void Lock(pthread_mutex_t mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void UnLock(pthread_mutex_t mutex)
    {
        pthread_mutex_unlock(&mutex);
    }
    RingQueue(int cap) : _cap(cap), _ring_queue(cap), _consumer_step(0), _productor_step(0)
    {
        // 初始化信号
        sem_init(&_room_sem, 0, _cap);
        sem_init(&_data_sem, 0, 0);

        pthread_mutex_init(&_productor_mutex, nullptr);
        pthread_mutex_init(&_consumer_mutex, nullptr);
    }
    void Enqueue(const T &in)
    {
        // 查看空间
        // 生产行为
        P(_room_sem);
        Lock(_productor_mutex);
        _ring_queue[_productor_step++] = in;//生产数据
        _productor_step %= _cap; // 防止越界
        UnLock(_productor_mutex);
        V(_data_sem);
    }
    void Pop(T *out)
    {
        // 消费行为
        P(_data_sem); // 放在锁前面是因为可以让线程们进行P操作，提高效率，就比如我们看电影买了票排队进场
        Lock(_consumer_mutex);
        *out = _ring_queue[_consumer_step++];
        _consumer_step %= _cap;
        UnLock(_consumer_mutex);
        V(_room_sem);
    }
    ~RingQueue()
    {
        sem_destroy(&_room_sem);
        sem_destroy(&_data_sem);

        pthread_mutex_destroy(&_productor_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
    }

private:
    /* data */
    // 定义队列

    int _cap;
    vector<T> _ring_queue;
    // 定义消费者和生产者的步数
    int _consumer_step;
    int _productor_step;
    // 定义信号
    sem_t _room_sem;
    sem_t _data_sem;
    // 4. 定义锁，维护多生产多消费之间的互斥关系
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;
};
